'''
Created on Jul 16, 2012

@author: thomas_dao
'''
from google.appengine.ext import ndb
from webapp2_extras.appengine.auth.models import User
from datetime import datetime
from app import cache_stats, cache_helper
import logging

class Article(ndb.Model):
    """
    An Article has title, original URL,
    and list of photos URL. It is shared by an User,
    with original status
    """
    title = ndb.StringProperty()
    url = ndb.StringProperty()
    photos = ndb.StringProperty(repeated=True)
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    updated_time = ndb.DateTimeProperty(auto_now=True)
    first_note = ndb.KeyProperty(kind="Note")
    author = ndb.KeyProperty(kind=User)
    
    # For statistics
    vote_up = ndb.IntegerProperty(default=0)
    vote_down = ndb.IntegerProperty(default=0)
    views = ndb.IntegerProperty(default=0)
    comments = ndb.IntegerProperty(default=0)
    
    # For query statistics
    day = ndb.IntegerProperty()
    week = ndb.IntegerProperty()
    month = ndb.IntegerProperty()
    year = ndb.IntegerProperty()
    
    def _pre_put_hook(self):
        if (self.day and self.week and self.month and self.year):
            return
        
        now = datetime.now()
        self.day = now.day
        self.week = now.isocalendar()[1]
        self.month = now.month
        self.year = now.year
        

class Note(ndb.Model):
    """
    An article can be shared by many users. Each user can write
    their own Note about the article. The note can be longer
    than 500 characters
    """
    user = ndb.KeyProperty(kind=User)
    note = ndb.TextProperty()
    board = ndb.KeyProperty(kind="Board")
    article = ndb.KeyProperty(kind="Article")
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    updated_time = ndb.DateTimeProperty(auto_now=True)
    
    def _post_put_hook(self, future):
        cache_helper.invalidate_notes_by_board(self.board)


class Comment(ndb.Model):
    """
    An User can comment on any URL. The URL can be photo, article URL
    Since the content of comment can be long,
    it is TextProperty
    """
    content = ndb.TextProperty()
    user = ndb.KeyProperty(kind=User)
    url = ndb.StringProperty()
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    
    def _post_put_hook(self, future):
        qry = Article.query(Article.url==self.url)
        article_key = qry.get(keys_only=True)
        if not article_key:
            return

        # Set vote on memcache
        cache_stats.increase_comment(article_key)
    
    
class Vote(ndb.Model):
    """
    An User can vote on an Article.
    A vote can be up or down
    """
    article = ndb.KeyProperty(kind="Article")
    user = ndb.KeyProperty(kind=User)
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    up = ndb.BooleanProperty()
    
    def _post_put_hook(self, future):
        # Set vote on memcache
        cache_stats.increase_vote(self)


class Board(ndb.Model):
    """
    Allow User to add a Note to a Board
    """
    user = ndb.KeyProperty(kind=User)
    name = ndb.StringProperty()
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    updated_time = ndb.DateTimeProperty(auto_now=True)
    followers = ndb.KeyProperty(kind=User, repeated=True)
    followers_count = ndb.IntegerProperty(default=0)
    private = ndb.BooleanProperty(default=False)
    
class FollowUser(ndb.Model):
    """
    Allow a user to follow another user
    """
    follower = ndb.KeyProperty(kind=User)
    followee = ndb.KeyProperty(kind=User)
    state = ndb.BooleanProperty(default=False)
    created_time = ndb.DateTimeProperty(auto_now_add=True)
    
    # Reset number of follower count to user
    def _post_put_hook(self, future):
        user = self.followee.get()
        if self.state:
            try:
                user.followers_count = user.followers_count + 1
            except:
                user.followers_count = 1
        else:
            try:
                user.followers_count = user.followers_count - 1
            except:
                user.followers_count = 0       
                     
        user.put()
    
    @classmethod
    def _post_delete_hook(cls, key, future):
        user = future.get_result().followee.get()
        user.put()
    